package com.zzyl.mapper;

import com.github.pagehelper.Page;
import com.zzyl.dto.BillPageQueryDto;
import com.zzyl.entity.finan.Bill;
import com.zzyl.vo.BillVo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;

@Mapper
public interface BillMapper {
	/**
	 * 根据主键删除
	 * @param id 主键
	 * @return 删除结果
	 */
	int deleteByElderId(Long id);
	
	/**
	 * 插入账单
	 * @param bill 账单实体
	 * @return 插入结果
	 */
	int insert(Bill bill);
	
	/**
	 * 选择性插入账单
	 * @param bill 账单实体
	 * @return 插入结果
	 */
	int insertSelective(Bill bill);
	
	/**
	 * 根据主键选择账单
	 * @param id 主键
	 * @return 账单实体
	 */
	Bill selectByPrimaryKey(Long id);
	
	/**
	 * 选择账单
	 * @param list
	 * @return 账单实体
	 */
	List<Bill> selectBytradingOrderNo(@Param("list") List<Long> list);
	
	/**
	 * 选择性更新账单
	 * @param bill 账单实体
	 * @return 更新结果
	 */
	int updateBytradingOrderNoSelective(Bill bill);
	
	
	/**
	 * 选择性更新账单
	 * @param bill 账单实体
	 * @return 更新结果
	 */
	int updateByIdSelective(Bill bill);
	
	/**
	 * 更新账单
	 * @param record 账单实体
	 * @return 更新结果
	 */
	int updateByPrimaryKey(Bill record);
	
	@Select("select * from bill where elder_id = #{elderId} and bill_month = #{month} and bill_type = 0 and check_in_code =#{checkInCode}")
	Bill selectByElderAndMonth(@Param("elderId") Long elderId,
	                           @Param("month") String month,
	                           @Param("checkInCode") String checkInCode);
	
	@Select("select * from bill where elder_id = #{elderId} and bill_type = 0 order by  bill_end_time desc limit 1")
	Bill selectLastByElder(@Param("elderId") Long elderId);
	
	@Select("select * from bill where elder_id = #{elderId} and bill_type = 0 order by  bill_end_time ASC limit 1")
	Bill selectFirstByElder(@Param("elderId") Long elderId);
	
	/**
	 * 查询未付押金的账单数量
	 * @param elderId 老人id
	 * @return 账单数量
	 */
	@Select("select count(1) from bill where elder_id = #{elderId} and transaction_status = 0 and deposit_amount > 0 and bill_type = 0 ")
	Long countUnPayDepositByElderAndStatus(@Param("elderId") Long elderId);
	
	
	List<Bill> selectDepositByEldersAndStatus(@Param("elderIds") List<Long> elderIds,
	                                          @Param("status") int status);
	
	/**
	 * 查询应退 （账单）
	 * @param elderId
	 * @param status
	 * @param time
	 * @return
	 */
	@Select("select * from bill where elder_id = #{elderId} and bill_type = 0 and transaction_status = #{status} and bill_end_time > #{time}  and check_in_code = #{checkInCode} ORDER BY create_time DESC ")
	List<Bill> selectDueBackByElder(@Param("elderId") Long elderId,
	                                @Param("status") int status,
	                                @Param("time") LocalDateTime time,
	                                @Param("checkInCode") String checkInCode);
	
	/**
	 * 关闭应退月度账单
	 * @param elderId      老人id
	 * @param checkOutTime 退住时间
	 */
	@Update("update bill set transaction_status=2 where elder_id = #{elderId} and bill_type = 0 and transaction_status = 1 and bill_end_time > #{checkOutTime}")
	void closeRetreatBill(@Param("elderId") Long elderId,
	                      @Param("checkOutTime") LocalDateTime checkOutTime);
	
	/**
	 * 关闭应退的订单账单
	 * @param tradingOrderNoList 交易系统订单号列表
	 */
	@Update("update bill set transaction_status =2 where trading_order_no in #{tradingOrderNoList}")
	void closeByTradingOrderNo(@Param("tradingOrderNoList") List<Long> tradingOrderNoList);
	
	/**
	 * 查询应退 （订单）
	 * @param elderId
	 * @param status
	 * @return
	 */
	@Select("select b.* from bill b left join `order` o  on o.trading_order_no = b.trading_order_no where b.elder_id = #{elderId} and o.status = 1 and b.bill_type = 1 and b.transaction_status = #{status} and check_in_code = #{checkInCode} ORDER BY b.create_time DESC ")
	List<Bill> selectOrderDueBackByElder(@Param("elderId") Long elderId,
	                                     @Param("status") int status,
	                                     @Param("checkInCode") String checkInCode);
	
	/**
	 * 查询欠费 (月度)
	 * @param elderId
	 * @param status
	 * @param time
	 * @return
	 */
	@Select("select * from bill where elder_id = #{elderId} and transaction_status = #{status} and bill_type = 0 and bill_start_time < #{time} and check_in_code = #{checkInCode} ORDER BY id asc ")
	List<Bill> selectArrearageByElder(@Param("elderId") Long elderId,
	                                  @Param("status") int status,
	                                  @Param("time") LocalDateTime time,
	                                  @Param("checkInCode") String checkInCode);
	
	/**
	 * 退住老人的欠费月度账单变为已支付
	 * @param elderId      老人id
	 * @param checkOutTime 退住时间
	 */
	@Update("update bill set transaction_status=1 where elder_id = #{elderId} and transaction_status = 0 and bill_type = 0 and bill_start_time < #{checkOutTime}")
	void payedArrearageBill(@Param("elderId") Long elderId,
	                        @Param("checkOutTime") LocalDateTime checkOutTime);
	
	/**
	 * 查询未缴 （订单）
	 * @param elderId
	 * @param status
	 * @return
	 */
	@Select("select * from bill where elder_id = #{elderId} and transaction_status = #{status} and bill_type = 1 ORDER BY create_time DESC ")
	List<Bill> selectUnpaidByElder(@Param("elderId") Long elderId,
	                               @Param("status") int status);
	
	/**
	 * 分页查询账单
	 * @param billNo      账单编号
	 * @param elderName   老人姓名
	 * @param elderIdCard 老人身份证号
	 * @param startTime   账单月份
	 * @return 分页结果
	 */
    /*Page<BillVo> page(@Param("billNo") String billNo,
                      @Param("elderName") String elderName,
                      @Param("elderIdCard") String elderIdCard,
                      @Param("startTime") LocalDateTime startTime,
                      @Param("endTime") LocalDateTime endTime,
                      @Param("transactionStatus") Integer transactionStatus,
                      @Param("elderIds") List<Long> elderIds);*/
	
	Page<BillVo> page(BillPageQueryDto dto);
	
	/**
	 * 分页查询欠费账单
	 * @param bedNo     床位号
	 * @param elderName 老人姓名
	 * @return 分页结果
	 */
	Page<BillVo> arrears(@Param("bedNo") String bedNo,
	                     @Param("elderName") String elderName);
	
	/**
	 * 批量选择性更新账单
	 * @param list              账单主键列表
	 * @param transactionStatus 交易状态
	 * @return 更新结果
	 */
	int batchUpdateByTradingOrderNoSelective(@Param("list") List<Long> list,
	                                         @Param("transactionStatus") int transactionStatus);
	
	/**
	 * 批量选择性更新账单
	 * @param list              账单主键列表
	 * @param transactionStatus 交易状态
	 * @return 更新结果
	 */
	int obatchUpdateByTradingOrderNoSelective(@Param("list") List<Long> list,
	                                          @Param("transactionStatus") int transactionStatus,
	                                          @Param("amount") BigDecimal amount);
	
	@Update("update bill set transaction_status = 2 where elder_id = #{elderId} and transaction_status = 0")
	void close(@Param("elderId") Long elderId);
	
	
	@Update("delete  from bill where elder_id = #{elderId} and bill_start_time > #{time}")
	void delete(@Param("elderId") Long elderId,
	            @Param("time") LocalDateTime time);
	
	
	@Select("select * from bill where bill_no = #{relNo} and bill_type = 1 order by  bill_end_time desc limit 1")
	Bill selectByBillNo(@Param("relNo") String relNo);
	
	/**
	 * 根据老人id和账单类型查询账单列表
	 * @param elderId 老人id
	 * @param type    账单类型@{@link com.zzyl.enums.BillType}
	 * @return 账单列表
	 */
	@Select("select * from bill where elder_id=#{elderId} and bill_type =#{type}")
	List<Bill> selectByElderAndType(@Param("elderId") Long elderId,
	                                @Param("type") Integer type);
	
	/**
	 * 查询退住时间之前未支付的账单
	 * @param checkInCode  入组编码
	 * @param checkOutTime 退住时间
	 * @return 账单列表
	 */
	@Select("select * from bill where bill_type=0 and transaction_status=0 and check_in_code=#{checkInCode} and bill_start_time <=#{checkOutTime}")
	List<Bill> selectBillBeforeRetreatTime(@Param("checkInCode") String checkInCode,
	                                       @Param("checkOutTime") LocalDateTime checkOutTime);
	
	/**
	 * 更新账单
	 * @param bill 账单
	 */
	@Update("update bill set transaction_status = #{transactionStatus},payable_amount = #{payableAmount} WHERE id = #{id}")
	void updateBill(Bill bill);
	
	/**
	 * 查询退住时间之后的账单
	 * @param checkInCode  入组编码
	 * @param checkOutTime 退住时间
	 * @return 账单列表
	 */
	@Select("select * from bill where bill_type=0 and check_in_code=#{checkInCode} and bill_start_time >#{checkOutTime}")
	List<Bill> selectBillAfterRetreatTime(@Param("checkInCode") String checkInCode,
	                                      @Param("checkOutTime") LocalDateTime checkOutTime);
}

